#include "devicewidget.h"

#include <QCheckBox>
#include <QDebug>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QRadioButton>
#include <QSlider>
#include <QStyle>
#include <QVBoxLayout>

#include <endpointvolume.h>

#include "endpointvolumeobject.h"

//hack
#include "ipolicyconfig.h"
const static IID IID_CPolicyConfigClient = __uuidof(CPolicyConfigClient);
const static IID IID_IPolicyConfig = __uuidof(IPolicyConfig);


DeviceWidget::DeviceWidget(QWidget *parent)
	: QWidget(parent),
	  DeviceObject(),
	  dvp(new DeviceWidgetPrivate),
	  device_name_label(new QLabel(this)),
	  edit_mode(false),
	  hbox_main(new QHBoxLayout),
	  lock_box(new QCheckBox(this)),
	  mute_box(new QCheckBox(this)),
	  radio_btn(new QRadioButton(this)),
	  vol_object(new EndpointVolumeObject(this)),
	  vol_slider(new QSlider(Qt::Horizontal, this))
	{
		QVBoxLayout * vbox = new QVBoxLayout(this);
		QHBoxLayout * hbox = new QHBoxLayout;

		dvp->device = NULL;
		dvp->device_type = eAll;
		dvp->endpoint_volume = NULL;

		hbox->addWidget(lock_box);
		hbox->addWidget(vol_slider);
		hbox->addWidget(mute_box);

		hbox_main->addWidget(radio_btn);
		hbox_main->addWidget(this);

		lock_box->setCursor(Qt::PointingHandCursor);
		lock_box->setText(tr("Lock"));

		connect(lock_box, SIGNAL(toggled(bool)),
				mute_box, SLOT(setDisabled(bool)));
		connect(lock_box, SIGNAL(toggled(bool)),
				vol_slider, SLOT(setDisabled(bool)));

		mute_box->setCursor(Qt::PointingHandCursor);
		mute_box->setText(tr("Mute"));

		connect(mute_box, SIGNAL(clicked(bool)),
				this, SLOT(mute(bool)));

		radio_btn->setCursor(Qt::PointingHandCursor);

		connect(radio_btn, SIGNAL(clicked()),
				this, SLOT(setAsDefaultDevice()));
		connect(radio_btn, SIGNAL(toggled(bool)),
				this, SLOT(repaint()));

		vbox->addWidget(device_name_label);
		vbox->addLayout(hbox);

		connect(vol_object, SIGNAL(deviceMuteChanged(bool)),
				this, SLOT(mute(bool)));
		connect(vol_object, SIGNAL(deviceVolumeChanged(int)),
				this, SLOT(setSliderPosition(int)));

		vol_slider->setMaximum(100);
		vol_slider->setPageStep(10);
		vol_slider->setSingleStep(2);
		vol_slider->setTickInterval(10);
		vol_slider->setTickPosition(QSlider::TicksAbove);
		vol_slider->setTracking(false);

		connect(vol_slider, SIGNAL(valueChanged(int)),
				this, SLOT(updateVolume()));
	}

DeviceWidget::~DeviceWidget()
	{
		if (dvp->endpoint_volume != NULL)
			dvp->endpoint_volume->UnregisterControlChangeNotify(vol_object);

		SAFE_RELEASE(dvp->device)
		SAFE_RELEASE(dvp->endpoint_volume)

		delete dvp;
	}

QString DeviceWidget::deviceName() const
	{
		return dvp->device_name;
	}

QStringList DeviceWidget::genSettings() const
	{
		QStringList settings;

		settings << dvp->device_name
				 << QString::number((int)lock_box->isChecked())
				 << QString::number(vol_slider->sliderPosition())
				 << QString::number((int)mute_box->isChecked())
				 << QString::number((int)radio_btn->isChecked());

		return settings;
	}

bool DeviceWidget::isDefaultDevice() const
	{
		return radio_btn->isChecked();
	}

void DeviceWidget::mute(bool x)
	{
		if (edit_mode)
			return;

		if (lock_box->isChecked())
			x = mute_box->isChecked();

		if (dvp->endpoint_volume != NULL)
			dvp->endpoint_volume->SetMute(x, NULL);

		mute_box->setChecked(x);
	}

void DeviceWidget::paintEvent(QPaintEvent *)
	{
		QPainter painter(this);

		QColor hilight(style()->standardPalette().window().color().lighter(104));
		QColor dark(style()->standardPalette().window().color().darker(100));

		if (isDefaultDevice())
		{
			QPen pen(dark.darker(170));
			painter.setPen(pen);

			QLinearGradient grad(width(), 0, width(), height());
			grad.setColorAt(0.48, hilight);
			grad.setColorAt(0.5, dark);

			hilight.setAlpha(100);
			dark.setAlpha(100);

			QLinearGradient grad2(width(), 0, width(), height());
			grad2.setColorAt(0.3, hilight);
			grad2.setColorAt(0.5, dark.darker(105));
			grad2.setColorAt(1, dark.darker(115));

			QBrush brush(grad);
			painter.setBrush(brush);

			painter.drawRoundedRect(0, 0, width()-1, height()-1, 2, 2);

			QBrush brush2(grad2);
			painter.setBrush(brush2);

			painter.drawRoundedRect(0, 0, width()-1, height()-1, 2, 2);
		}

		else
		{
			QPen pen(dark.darker(110));
			painter.setPen(pen);

			painter.drawRoundedRect(0, 0, width()-1, height()-1, 2, 2);
		}
	}

void DeviceWidget::setAsDefaultDevice()
	{
		if (edit_mode)
			return;

		HRESULT hr;
		LPWSTR dev_id;

		dvp->device->GetId(&dev_id);

		IPolicyConfig * policy_conf;

		hr = CoCreateInstance(IID_CPolicyConfigClient,
							  NULL,
							  CLSCTX_ALL,
							  IID_IPolicyConfig,
							  (LPVOID *)&policy_conf);

		if (hr == S_OK)
		{
			hr = policy_conf->SetDefaultEndpoint(dev_id, eConsole);
			hr = policy_conf->SetDefaultEndpoint(dev_id, eMultimedia);

			SAFE_RELEASE(policy_conf)
			CoTaskMemFree(dev_id);
		}

	}

void DeviceWidget::setDevice(IMMDevice * device)
	{
		dvp->device = device;
		device->Activate(__uuidof(IAudioEndpointVolume),
						 CLSCTX_ALL,
						 NULL,
						 (void**)&dvp->endpoint_volume);
		syncMute();
		syncVolume();
		if (dvp->endpoint_volume != NULL)
			dvp->endpoint_volume->RegisterControlChangeNotify(vol_object);
	}

void DeviceWidget::setDeviceName(const QString & name)
	{
		device_name_label->setText(name);
		dvp->device_name = name;
	}

void DeviceWidget::setEditMode(bool x)
	{
		if (x)
		{
			setDefaultLocked(lock_box->isChecked());
			setDefaultMute(mute_box->isChecked());
			setDefaultVolume(vol_slider->sliderPosition());
		}

		else
		{
			lock_box->setChecked(defaultLocked());
			mute_box->setChecked(defaultMute());
			vol_slider->setSliderPosition(defaultVolume());
		}

		edit_mode = x;
	}

void DeviceWidget::setLocked(bool l)
	{
		lock_box->setChecked(l);
	}

void DeviceWidget::setSliderPosition(int p)
	{
		if (lock_box->isChecked())
			setVolume(p);

		else if (!vol_slider->isSliderDown())
			vol_slider->setSliderPosition(p);
	}

void DeviceWidget::setVolume(int v)
	{
		if (edit_mode)
		{
			vol_slider->setSliderPosition(v);
			return;
		}

		if (lock_box->isChecked())
			v = vol_slider->sliderPosition();

		if (dvp->endpoint_volume != NULL)
		{
			float i = 0;
			if (v)
				i = (float) v / 100;
			dvp->endpoint_volume->SetMasterVolumeLevelScalar(i, NULL);
			vol_slider->setStatusTip(QString::number(i));
		}
	}

void DeviceWidget::syncMute()
	{
		if (dvp->endpoint_volume != NULL)
		{
			BOOL x;
			dvp->endpoint_volume->GetMute(&x);
			mute_box->setChecked(x);
			vol_object->setCurrentMute(x);
		}
	}

void DeviceWidget::syncVolume()
	{
		if (dvp->endpoint_volume != NULL)
		{
			float i;
			dvp->endpoint_volume->GetMasterVolumeLevelScalar(&i);
			int v = i*100;
			vol_slider->setSliderPosition(v);
//			vol_object->setCurrentVolume(v);
		}
	}

void DeviceWidget::updateVolume()
	{
		setVolume(vol_slider->sliderPosition());
	}
